package com.anry.weatherforecast.service;

import com.anry.weatherforecast.response.WeatherConditionResponse;
import com.anry.weatherforecast.utils.FixedAliYunSignatureUtil;
import okhttp3.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 修复的天气实况API调用服务
 */
@Service
public class FixedWeatherConditionService {
    @Value("${anry.appkey}")
    private String APP_KEY;

    @Value("${anry.appsecret}")
    private String APP_SECRET;

    private static final String API_URL = "https://aliv18.data.moji.com/whapi/json/alicityweather/condition";
    private static final String TOKEN = "50b53ff8dd7d9fa320d3d3ca32cf8ed1";

    private final OkHttpClient client;
    public final ObjectMapper objectMapper = new ObjectMapper();


    public FixedWeatherConditionService() {
        this.client = createUnsafeOkHttpClient();
    }


    /**
     * 创建跳过SSL验证的HTTP客户端
     */
    private OkHttpClient createUnsafeOkHttpClient() {
        try {
            javax.net.ssl.X509TrustManager trustManager = new javax.net.ssl.X509TrustManager() {
                @Override
                public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {
                }

                @Override
                public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {
                }

                @Override
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return new java.security.cert.X509Certificate[]{};
                }
            };

            javax.net.ssl.SSLContext sslContext = javax.net.ssl.SSLContext.getInstance("SSL");
            sslContext.init(null, new javax.net.ssl.TrustManager[]{trustManager}, new java.security.SecureRandom());

            return new OkHttpClient.Builder()
                    .sslSocketFactory(sslContext.getSocketFactory(), trustManager)
                    .hostnameVerifier((hostname, session) -> true)
                    .connectTimeout(30, TimeUnit.SECONDS)
                    .readTimeout(30, TimeUnit.SECONDS)
                    .writeTimeout(30, TimeUnit.SECONDS)
                    .build();

        } catch (Exception e) {
            throw new RuntimeException("创建HTTP客户端失败", e);
        }
    }

    /**
     * 获取天气实况数据（使用修复的签名算法）
     */
    public String getWeatherCondition(String cityId) throws Exception {
        System.out.println("=== 开始查询城市ID: " + cityId + " ===");

        // 1. 准备参数
        Map<String, String> formParams = new HashMap<>();
        formParams.put("cityId", cityId);
        formParams.put("token", TOKEN);

        String formBodyString = buildFormBody(formParams);
        System.out.println("请求体: " + formBodyString);

        RequestBody body = RequestBody.create(
                formBodyString,
                MediaType.parse("application/x-www-form-urlencoded; charset=utf-8")
        );

        // 2. 准备签名参数
        String timestamp = FixedAliYunSignatureUtil.getCurrentTimestamp();
        String nonce = FixedAliYunSignatureUtil.generateNonce();

        // 参与签名的Headers
        Map<String, String> signHeaders = new HashMap<>();
        signHeaders.put("X-Ca-Key", APP_KEY);
        signHeaders.put("X-Ca-Timestamp", timestamp);
        signHeaders.put("X-Ca-Nonce", nonce);

        String signatureHeaders = FixedAliYunSignatureUtil.getSignatureHeaders(signHeaders);
        System.out.println("参与签名的Headers: " + signatureHeaders);

        // 3. 计算Content-MD5（根据服务器返回，这个字段在签名中为空）
        String contentMD5 = ""; // 服务器签名中不需要Content-MD5

        // 4. 计算签名（使用修复的算法）
        // 修改Content-Type为不带charset的版本
        // 签名计算时使用带charset的Content-Type
        // 签名计算和请求头中使用一致的Content-Type
        String signature = FixedAliYunSignatureUtil.calculateSignature(
                APP_SECRET,
                "POST",
                "application/json",
                "", // Content-MD5为空
                "application/x-www-form-urlencoded; charset=utf-8",
                "", // Date为空
                signHeaders,
                "/whapi/json/alicityweather/condition",
                null,
                formParams
        );

        Headers headers = new Headers.Builder()
                .add("Content-Type", "application/x-www-form-urlencoded; charset=utf-8")
                .add("Accept", "application/json")
                .add("X-Ca-Key", APP_KEY)
                .add("X-Ca-Signature", signature)
                .add("X-Ca-Timestamp", timestamp)
                .add("X-Ca-Nonce", nonce)
                .add("X-Ca-Signature-Headers", signatureHeaders)
                .build();


        // 6. 发送请求
        Request request = new Request.Builder()
                .url(API_URL)
                .headers(headers)
                .post(body)
                .build();

        System.out.println("发送POST请求到: " + API_URL);

        try (Response response = client.newCall(request).execute()) {
            System.out.println("响应状态码: " + response.code());
            System.out.println("响应消息: " + response.message());

            // 打印响应头
            System.out.println("响应头:");
            for (String name : response.headers().names()) {
                System.out.println("  " + name + ": " + response.headers().get(name));
            }

            if (!response.isSuccessful()) {
                String errorBody = response.body() != null ? response.body().string() : "无响应体";
                System.out.println("错误响应体: " + errorBody);

                // 检查是否有详细的错误信息
                String errorMessage = response.header("X-Ca-Error-Message");
                if (errorMessage != null) {
                    System.out.println("详细错误信息: " + errorMessage);
                }

                throw new RuntimeException("API请求失败: " + response.code() + " - " + response.message());
            }

            ResponseBody responseBody = response.body();
            if (responseBody != null) {
                String result = responseBody.string();
                System.out.println("请求成功！响应长度: " + result.length());
                System.out.println("响应内容: " + result);
                return result;
            } else {
                throw new RuntimeException("响应体为空");
            }
        }
    }

    /**
     * 构建Form格式的请求体
     */
    private String buildFormBody(Map<String, String> params) {
        StringBuilder sb = new StringBuilder();
        try {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                if (sb.length() > 0) {
                    sb.append("&");
                }
                sb.append(URLEncoder.encode(entry.getKey(), "UTF-8"))
                        .append("=")
                        .append(URLEncoder.encode(entry.getValue(), "UTF-8"));
            }
        } catch (Exception e) {
            throw new RuntimeException("构建请求体失败", e);
        }
        return sb.toString();
    }

    /**
     * 获取天气实况并解析为对象
     */
    public WeatherConditionResponse getWeatherConditionParsed(String cityId) throws Exception {
        String responseJson = getWeatherCondition(cityId);
        return objectMapper.readValue(responseJson, WeatherConditionResponse.class);
    }

}